home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / appl / napsaterm / wimp.c < prev    next >
C/C++ Source or Header  |  1994-05-14  |  24KB  |  1,133 lines

  1. /*
  2.  * wimp.c --- Intuition interface
  3.  *
  4.  * Author: ppessi <Pekka.Pessi@hut.fi>
  5.  *
  6.  * Copyright (c) 1993 Pekka Pessi
  7.  *
  8.  * Created      : Wed Nov 10 11:15:14 1993 ppessi
  9.  * Last modified: Fri Feb  4 03:24:24 1994 ppessi
  10.  *
  11.  * $Log: wimp.c,v $
  12.  * Revision 3.4  1994/05/14  14:12:58  ppessi
  13.  * Merged changes from Napsaterm 3.5 by R. Knop
  14.  *
  15.  * Revision 3.3  1994/02/25  02:02:17  ppessi
  16.  * Updated some IDCMP macros
  17.  *
  18.  * Revision 3.2  1994/01/08  08:58:31  ppessi
  19.  * Added optional error message requesters;
  20.  * fixed menu_move() and menu_execute()
  21.  *
  22.  * Revision 3.1  94/01/07  22:51:48  ppessi
  23.  * Version 3 beta
  24.  * 
  25.  * Revision 2.3  93/11/24  18:31:01  ppessi
  26.  * Changed the memory management slightly
  27.  * 
  28.  * Revision 2.2  93/11/18  18:33:24  ppessi
  29.  * Changed menu format.
  30.  * 
  31.  * Revision 2.1  93/11/17  15:41:30  ppessi
  32.  * Moved the rest of the Intuition code here
  33.  * mapwindow() opens the window with OpenWindowTags()
  34.  * 
  35.  * Revision 2.0  93/11/15  03:39:31  ppessi
  36.  * Version 2 initial revision
  37.  * 
  38.  */
  39.  
  40. RCS_ID_C= "$Id: wimp.c,v 3.4 1994/05/14 14:12:58 ppessi Exp $";
  41.  
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include "nifty.h"
  46. #include "amiga.h"
  47. #include "napsaprefs.h"
  48.  
  49. #include "nio.h"
  50. #include "display.h"
  51. #include "dispmacros.h"
  52.  
  53. #include "wimp.h"
  54.  
  55. #include <assert.h>
  56. #include <stdarg.h>
  57.  
  58. #include <intuition/intuition.h>
  59.  
  60. #if USE_PRAGMAS
  61. #include <proto/intuition.h>
  62. #endif
  63. #if USE_INLINE
  64. #include <inline/intuition.h>
  65. #endif
  66. #if USE_CLIB
  67. #include <clib/intuition_protos.h>
  68. #endif
  69.  
  70. /* This is private */
  71. #ifndef TEKTRONICS      /*added RKNOP 940328*/
  72. static struct Window *w = NULL;
  73. #else
  74. struct Window *w = NULL;    /*tek4010.c needs this window definition*/
  75. #endif
  76. static struct MsgPort *winport = NULL;
  77. /* We publish only the geometry */
  78. struct geometry wm = { -1, -1, 80, 24 };
  79.  
  80. #define WM_MINWIDTH 180        /* Minimum height */
  81.  
  82. static struct {
  83.   UWORD left, top, width, height;
  84. } zoom_size = 
  85. { 0, 0, WM_MINWIDTH, 0 };
  86.  
  87. #define MY_IDCMP_FLAGS \
  88.  ( IDCMP_CLOSEWINDOW  | IDCMP_NEWSIZE   | IDCMP_MENUPICK | \
  89.    IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | \
  90.    IDCMP_CHANGEWINDOW )
  91.  
  92. static void parsegeometry(char *gs, struct geometry *gm);
  93. int mapwindow(void);
  94. void unmapwindow(void);
  95.  
  96. void domouse(struct IntuiMessage * msg);
  97.  
  98. /*
  99.  * display start routine -- sets up display
  100.  */
  101. void dsinit(void)
  102. {
  103.   initkeys();
  104.   initnations();
  105.   initfonts();
  106.  
  107.   /* Set the default geometry */
  108.   clearSelection();
  109.  
  110.   disp.visual = np.visual;
  111.   disp.blink = np.blink;
  112.   disp.invert = np.invert;
  113.   disp.style = 0;
  114.   disp.curx = disp.cury = disp.winheight = disp.winwidth = 0;
  115.  
  116.   allocate_display(MAXWIDTH, MAXHEIGHT);
  117.  
  118.   parsegeometry(np.geometry, &wm);
  119.  
  120.   if (!mapwindow()) 
  121.     fatalError(MEMORY_ERROR_MSG);
  122.  
  123.   dssizewindow(0, 0, np.col80);
  124.  
  125.   reset_display(0);
  126.   redraw_display(1);
  127. }
  128.  
  129. long dsmask(void)
  130. {
  131.   if (w)
  132.     return 1 << winport->mp_SigBit;
  133.   else
  134.     return 0;
  135. }
  136.  
  137. /*
  138.  * Quit 
  139.  */
  140. void dsquit(void)
  141. {
  142.   ClipClose();
  143.   free_display();
  144.  
  145.   if (w) 
  146.     unmapwindow();
  147.  
  148.   deinitfonts();
  149.   deinitkeys();
  150.   deinitnations();
  151. }
  152.  
  153. /*
  154.  * Set the geometry as specified
  155.  */
  156. static void parsegeometry(char *gs, struct geometry *gm)
  157. {
  158.   long left, top, width, height;
  159.   int eaten;
  160.  
  161.   if (gs == NULL || gs[0] == '\0')
  162.     return;
  163.  
  164.   eaten = StrToLong(gs, &left);
  165.   gs += eaten;
  166.   if (eaten < 0 || *gs++ != '/')
  167.     return;
  168.     
  169.   eaten = StrToLong(gs, &top);
  170.   gs += eaten;
  171.   if (eaten < 0 || *gs++ != '/')
  172.     return;
  173.     
  174.   eaten = StrToLong(gs, &width);
  175.   gs += eaten;
  176.   if (eaten < 0 || *gs++ != '/')
  177.     return;
  178.   if (np.col80)
  179.     width = 80;
  180.  
  181.   eaten = StrToLong(gs, &height);
  182.   if (eaten < 0 )
  183.     return;
  184.  
  185.   /* set user's geometry */
  186.   gm->left = left; 
  187.   gm->top = top; 
  188.   gm->width = width;
  189.   gm->height = height;
  190. }
  191.  
  192. /*
  193.  * Wait a key press 
  194.  */
  195. void waitToEnd(void)
  196. {
  197.   int class;
  198.   struct IntuiMessage *msg;
  199.  
  200.   dscursoroff();
  201.   dscursormove(NEXT_LINE, 1);
  202.   (void) dsstyle(INVERSE1);
  203.   dsputs("** Press any key to exit. **");
  204.   dscursoron();
  205.  
  206.   do {
  207.     msg = (struct IntuiMessage *)GetMsg(winport);
  208.     if (!msg) {
  209.       WaitPort(winport);
  210.       continue;
  211.     }
  212.     class = msg->Class;
  213.     ReplyMsg(msg);
  214.   } while (class != RAWKEY);
  215. }
  216.  
  217. /*
  218.  * DisplayBeep()
  219.  */
  220. void displaybell(void)
  221. {
  222.   if (w) 
  223.     DisplayBeep(w->WScreen);
  224. }
  225.  
  226. /* 
  227.  * Event handler for intuition events.
  228.  */
  229. void dspoll(void)
  230. {
  231.   struct IntuiMessage *msg;
  232.     
  233.   while (w && (msg = (struct IntuiMessage *)GetMsg(winport))) {
  234.     switch(msg->Class) {
  235.     case IDCMP_RAWKEY:
  236.       dokeys(msg);
  237.       break;
  238.     case IDCMP_CLOSEWINDOW:
  239.       ReplyMsg((struct Message *)msg);
  240.       dsquit();
  241.       amigaquit();
  242.       exit(0);
  243.       break;
  244.     case IDCMP_NEWSIZE:
  245.       ReplyMsg((struct Message *)msg);
  246.       redraw_display(1);
  247.       break;
  248.     case IDCMP_MENUPICK:
  249.       domenu(msg);
  250.       break;
  251.     case IDCMP_MOUSEMOVE:
  252.     case IDCMP_MOUSEBUTTONS:
  253.       domouse(msg);
  254.       break;
  255. #ifdef OWNICONIFY
  256.     case IDCMP_GADGETDOWN:
  257.       if (DoubleClick(secs, mics, msg->Seconds, msg->Micros)) {
  258.     ReplyMsg((struct Message *)msg);
  259.     while (msg = (struct IntuiMessage *)GetMsg(w->UserPort)) 
  260.       ReplyMsg((struct Message *)msg);
  261.     deiconify();
  262.     mapwindow();
  263.       }
  264.       else {
  265.     secs = msg->Seconds; mics = msg->Micros;
  266.     ReplyMsg((struct Message *)msg);
  267.       }
  268.       break; 
  269. #endif
  270.     default:
  271.       ReplyMsg((struct Message *)msg);
  272.     }
  273.   }
  274. }
  275.  
  276. /*
  277.  * Convert Amiga mouse events to doselection() format
  278.  */
  279. void domouse(struct IntuiMessage *msg)
  280. {
  281.   int x, y, count = 0;
  282.  
  283.   x = GETXPOS(msg->MouseX);
  284.   y = GETYPOS(msg->MouseY);
  285.   BOUNDSCK(x, 0, disp.winwidth);
  286.   BOUNDSCK(y, 0, disp.winheight-1);
  287.  
  288.   if (msg->Class == MOUSEBUTTONS) {
  289.     if (np.mouse & MOUSE_BOTH) {
  290.       register char mousequal = 0x40;
  291.  
  292.       iobuf[0] = ESC;
  293.       iobuf[1] = 'M';
  294.  
  295.       if (msg->Code == SELECTUP) {
  296.     mousequal |= 1 << 5;
  297.     count = 5;
  298.       }
  299.       if (msg->Code == SELECTDOWN) {
  300.     mousequal |= 1 << 4;
  301.     count = 5;
  302.       }
  303.       if (msg->Qualifier & IEQUALIFIER_CAPSLOCK)
  304.     mousequal |= 1 << 3;
  305.       if (msg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  306.     mousequal |= 1 << 2;
  307.       if (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  308.     mousequal |= 1 << 1;
  309.       if (msg->Qualifier & IEQUALIFIER_CONTROL)
  310.     mousequal |= 1 << 0;
  311.       iobuf[2] = mousequal;
  312.       iobuf[3] = ' ' + x;
  313.       iobuf[4] = ' ' + y;
  314.     }
  315.  
  316.     if (msg->Code == SELECTDOWN) {
  317.       ReportMouse(TRUE, w);
  318.       doselection(LBDOWN, x, y);
  319.     }
  320.     if (msg->Code == SELECTUP) {
  321.       ReportMouse(FALSE, w);
  322.       doselection(LBUP, x, y);
  323.     }
  324.   } else if (msg->Class == MOUSEMOVE) {
  325.     doselection(LMOVE, x, y);
  326.   }
  327.  
  328.   ReplyMsg((struct Message *)msg);
  329.   if (count)
  330.     nwrite(iobuf, count);
  331. }
  332.  
  333. #include <utility/tagitem.h>
  334.  
  335. int mapwindow(void)
  336. {
  337.   char *pubscname = np.pubscname;
  338.  
  339.   /* Try to find specified public screen */
  340.   struct Screen *s = LockPubScreen(pubscname);
  341.   /* If not successful, try default */
  342.   if (!s && pubscname) {
  343.     s = LockPubScreen(pubscname = NULL);
  344.   }
  345.   /* Give up */
  346.   if (!s)
  347.     return 0;
  348.  
  349. #define OPTIONAL(condition, tag) ((condition) ? (tagname), TAG_IGNORE)
  350.  
  351.   zoom_size.top = wm.top < 0 ? s->BarHeight : wm.top;
  352.   if (wm.left != -1) {
  353.     zoom_size.left = wm.left;
  354.   }
  355.   zoom_size.height = s->WBorTop + s->Font->ta_YSize + 1;
  356.  
  357.   w = OpenWindowTags(NULL, 
  358.              WA_PubScreen, s,
  359.              WA_InnerWidth, (ULONG)wm.font.w * wm.width,
  360.              WA_InnerHeight, (ULONG)wm.font.h * wm.height,
  361.              wm.left != -1 ? WA_Left : TAG_IGNORE, (ULONG)wm.left,
  362.              WA_Top, zoom_size.top,
  363.              np.size_gadget ? WA_SizeGadget : TAG_SKIP, 1L,
  364.              np.size_gadget == SIZE_COLUMN ? 
  365.              WA_SizeBRight : WA_SizeBBottom, 1L,
  366.              WA_ScreenTitle, ProgName,
  367.              WA_Zoom, &zoom_size,
  368.              WA_Flags, 
  369.              WFLG_SMART_REFRESH | WFLG_CLOSEGADGET 
  370.              | WFLG_DEPTHGADGET | WFLG_DRAGBAR 
  371.              | WFLG_NOCAREREFRESH | WFLG_ACTIVATE,
  372.              WA_IDCMP, MY_IDCMP_FLAGS,
  373.              TAG_DONE );
  374.   UnlockPubScreen(NULL, s);
  375.  
  376.   if (!w)
  377.     return 0;
  378.  
  379.   winport = w->UserPort;
  380.   initmenus();
  381.  
  382. #if 0 
  383.   Move(rp, 0, 0);
  384.   BltBitMapRastPort(rp->BitMap, 0, 0, rp, w->BorderLeft, w->BorderTop, 
  385.             w->Width - w->BorderLeft - w->BorderRight,
  386.             w->Height - w->BorderTop - w->BorderBottom, WHITE);
  387. #endif
  388.  
  389.   return 1;
  390. }
  391.  
  392. void unmapwindow(void)
  393. {   
  394.   if (w) {
  395.     wm.left = w->LeftEdge;
  396.     wm.top = w->TopEdge;
  397.  
  398.     ClearMenuStrip(w);
  399.     
  400.     deinitmenus();
  401.     
  402.     ModifyIDCMP(w, 0);
  403.     CloseWindow(w);
  404.     w = NULL;
  405.  
  406.     deinitdrawing();
  407.   }
  408. }
  409.  
  410. /*
  411.  * Handle resizing the display
  412.  */
  413. int resize_display(void)
  414. {
  415.   register int style;
  416.   int xsz, ysz;
  417.   int redrawn;
  418.  
  419.   if (!w) 
  420.     return 0;
  421.  
  422.   wm.xoff = w->BorderLeft;
  423.   wm.yoff = w->BorderTop;
  424.  
  425.   wm.x = w->Width - w->BorderRight - w->BorderLeft;
  426.   wm.width = xsz = wm.x / wm.font.w;
  427.  
  428.   wm.y = w->Height - w->BorderBottom - w->BorderTop;
  429.   wm.height = ysz = wm.y / wm.font.h;
  430.  
  431.   if (np.col80 && xsz > 80)
  432.     xsz = 80;
  433.  
  434.   if (xsz < MINWIDTH || ysz < MINHEIGHT) {
  435.     deinitdrawing();
  436.     showbanner(w->RPort, "Make me BIGGER");
  437.     return 0;
  438.   }
  439.  
  440.   redrawn = initdrawing(w->RPort);
  441.  
  442.   if (!redrawn && xsz == disp.winwidth && ysz == disp.winheight) {
  443.     return redrawn;
  444.   }
  445.  
  446.   BOUNDSCK(xsz, MINWIDTH, disp.maxwidth);
  447.   BOUNDSCK(ysz, MINHEIGHT, disp.maxheight);
  448.  
  449.   if ((disp.scrolltop == 0 && disp.scrollbot == disp.winheight-1) ||
  450.       disp.scrollbot >= ysz)
  451.     disp.scrollbot = ysz-1;
  452.   if (disp.scrolltop >= ysz)
  453.     disp.scrolltop = 0;
  454.   if (disp.cury >= ysz) {
  455.     deinitdrawing();
  456.     dsscroll(0, disp.winheight, disp.cury - ysz + 1);
  457.     initdrawing(w->RPort);
  458.     disp.cury = ysz - 1;
  459.   }
  460.   disp.winwidth = xsz, disp.winheight = ysz;
  461.  
  462.   dssizewindow(xsz, ysz, 0);
  463.  
  464.   DSRESIZE();
  465.  
  466.   niosize(ysz, xsz, wm.x, wm.y);
  467.  
  468.   setnewtitle();
  469.   return 1;
  470. }
  471.  
  472. /*
  473.  * Set window size according the given display size
  474.  */
  475. void dssizewindow(int width, int height, int widthflag)
  476. {
  477.   if (!w) {
  478.     return;
  479.   } else {
  480.     int ow = w->Width, nw;
  481.     int oh = w->Height, nh;
  482.  
  483.     if (width)
  484.       nw = MIN(width * wm.font.w + w->BorderLeft + w->BorderRight, 
  485.            w->WScreen->Width);
  486.     else
  487.       nw = ow;
  488.  
  489.     if (height)
  490.       nh = MIN(height * wm.font.h + w->BorderTop + w->BorderBottom, 
  491.            w->WScreen->Height);
  492.     else 
  493.       nh = oh;
  494.     
  495.     if ((nw-ow) || (nh-oh)) {
  496.       SizeWindow(w, nw - ow, nh - oh);
  497. #if 0
  498.       /* wait for resize message */
  499.       WaitPort(w->UserPort);
  500. #endif
  501.     }
  502.  
  503.     if (np.col80) {
  504.       WindowLimits(w, nw, zoom_size.height, nw, 0);
  505.     } else {
  506.       WindowLimits(w, zoom_size.width, zoom_size.height, 
  507.            MAXWIDTH * wm.font.w, MAXHEIGHT * wm.font.h);
  508.     }
  509.   }
  510. }
  511.  
  512. /*
  513.  * Handle window and screen titles
  514.  */
  515. #ifndef MAXHOSTNAMELEN
  516. #define MAXHOSTNAMELEN 64
  517. #endif
  518.  
  519. void setnewtitle(void)
  520. {
  521.   static char Title[MAXHOSTNAMELEN + 16];
  522.  
  523.   int rows = wm.height, cols = wm.width;
  524.  
  525.   if (np.title)
  526.     strncpy(Title, np.title, sizeof(Title));
  527.   else
  528.     strcpy(Title, ProgName);
  529.   strncat(Title, " (", sizeof(Title));
  530.   strncat(Title, itos(cols), sizeof(Title));
  531.   strncat(Title, " x ", sizeof(Title));
  532.   strncat(Title, itos(rows), sizeof(Title));
  533.   strncat(Title, ")", sizeof(Title));
  534.  
  535.   if (w)
  536.     SetWindowTitles(w, Title, (UBYTE*)ProgName);
  537. }
  538.  
  539. #include <errno.h>
  540.  
  541. /*
  542.  * Print the IO error messages
  543.  */
  544. void perror(const char *banner)
  545. {
  546.   const char *error = strerror(errno);
  547.  
  548.   if (started_from_workbench && IntuitionBase != NULL) {
  549.     struct EasyStruct libraryES;
  550.  
  551.     libraryES.es_StructSize = sizeof(libraryES);
  552.     libraryES.es_Flags = 0;
  553.     libraryES.es_Title = ProgName;
  554.     libraryES.es_TextFormat = "%s: %s";
  555.     libraryES.es_GadgetFormat = "Continue";
  556.     
  557.     EasyRequest(w, &libraryES, NULL, banner, error);
  558.   } else {
  559.     Printf("%s: %s\n", banner, error);
  560.   }
  561. }
  562.  
  563. void herror(const char *banner, const char *error)
  564. {
  565.   if (started_from_workbench && IntuitionBase != NULL) {
  566.     struct EasyStruct libraryES;
  567.  
  568.     libraryES.es_StructSize = sizeof(libraryES);
  569.     libraryES.es_Flags = 0;
  570.     libraryES.es_Title = ProgName;
  571.     libraryES.es_TextFormat = "%s: %s";
  572.     libraryES.es_GadgetFormat = "Continue";
  573.     
  574.     EasyRequest(w, &libraryES, NULL, banner, error);
  575.   } else {
  576.     Printf("%s: %s\n", banner, error);
  577.   }
  578. }
  579.  
  580. /*
  581.  * Print the error message and die
  582.  */
  583. void fatalError(const char *s, ...)
  584. {
  585.   va_list va;
  586.   va_start(va, s);
  587.  
  588.   if (started_from_workbench && IntuitionBase != NULL) {
  589.     struct EasyStruct libraryES;
  590.  
  591.     libraryES.es_StructSize = sizeof(libraryES);
  592.     libraryES.es_Flags = 0;
  593.     libraryES.es_Title = ProgName;
  594.     libraryES.es_TextFormat = s;
  595.     libraryES.es_GadgetFormat = "Quit";
  596.     
  597.     EasyRequestArgs(w, &libraryES, NULL, va);
  598.   } else {
  599.     PutStr(PROGNAME ": ");
  600.     VPrintf(s, (LONG *)va);
  601.     va_end(va);
  602.     PutStr("\n");
  603.   }
  604.  
  605.   dsquit();
  606.   amigaquit();
  607.   exit(130);
  608. }
  609.  
  610. /*
  611.  * Menus
  612.  */
  613. #define MENU_CMD      0
  614. #define MENU_EDIT     1
  615. #define MENU_SETUP    2
  616.  
  617. #if 0
  618. #define MENU_NATIONAL 3
  619. static struct Menu nationalmenu = {
  620.   NULL, 120, 0, 55, 10, MENUENABLED, (BYTE *)"National", 0, 0, 0, 0, 0,
  621. };
  622. #endif
  623.  
  624. static struct Menu setupmenu = {
  625.   NULL, 55, 0, 45, 10, MENUENABLED, (BYTE *)"Setup", 0, 0, 0, 0, 0,
  626. };
  627.  
  628. static struct Menu editmenu = {
  629.   &setupmenu, 2, 0, 45, 10, MENUENABLED, (BYTE *)"Edit", 0, 0, 0, 0, 0,
  630. };
  631.  
  632. static struct Menu cmdmenu = {
  633.   &editmenu, 2, 0, 45, 10, MENUENABLED, (BYTE *)"Command", 0, 0, 0, 0, 0,
  634. };
  635.  
  636. /* These macros use some fudge factors to make manus look good */
  637. /* 9 is space between menus in the menu bar */
  638. #define MENUWIDTH(menu) (9 + \
  639.   TextLength(&(w->WScreen->RastPort), (menu).MenuName, strlen((menu).MenuName)))
  640.  
  641. /* 35 is the approximate size of the "A" symbol in the menus */
  642. #define CMDWIDTH(cmd) (35 + \
  643.   TextLength(&(w->WScreen->RastPort), &(cmd), 1))
  644.  
  645. #define ITEMWIDTH(str) \
  646.   TextLength(&(w->WScreen->RastPort), (UBYTE*)(str), strlen(str));
  647.  
  648. /*
  649.  * Menu callback utility functions
  650.  */
  651. static void menu_state(UBYTE mnum, UBYTE inum, UBYTE subnum, UBYTE enabled)
  652. {
  653.   struct Menu *menu;
  654.   struct MenuItem *item;
  655.  
  656.   for (menu = &cmdmenu; mnum > 0; mnum--)
  657.     menu = menu->NextMenu;
  658.   for (item = menu->FirstItem; inum > 0; inum--)
  659.     item = item->NextItem;
  660.   /* subnum is ignored for now */
  661.   assert(subnum == NOSUB);
  662.  
  663.   if (enabled)
  664.     item->Flags |= ITEMENABLED;
  665.   else
  666.     item->Flags &= ~ITEMENABLED;
  667. }
  668.  
  669.  
  670. /*
  671.  * Menu callback routines 
  672.  */
  673. void menu_move(UBYTE mnum, UBYTE item, UBYTE sub)
  674. {
  675.   if (isSelection()) {
  676.     char *selstring, *temp;
  677.     if ((temp = selstring = grabSelection())) {
  678.       while (*temp++) 
  679.     ;
  680.       nwrite(selstring, temp - selstring - 1);
  681.       FreeVec(selstring);
  682.     }
  683.   }
  684. }
  685.  
  686. void menu_execute(UBYTE mnum, UBYTE item, UBYTE sub)
  687. {
  688.   if (isSelection()) {
  689.     menu_move(mnum, item, sub);
  690.     nwrite("\n", 1);
  691.   }
  692. }
  693.  
  694. void menu_copy(UBYTE mnum, UBYTE item, UBYTE sub)
  695. {
  696.   if (isSelection()) {
  697.     char *selstring = grabSelection();
  698.     ClipCut(selstring);
  699.     FreeVec(selstring);
  700.   }
  701. }
  702.  
  703. void menu_paste(UBYTE mnum, UBYTE item, UBYTE sub)
  704. {
  705.   nwrite(iobuf, ClipPaste(iobuf, sizeof(iobuf)));
  706. }
  707.  
  708. void menu_clear(UBYTE mnum, UBYTE item, UBYTE sub)
  709. {
  710.   dscursoroff();
  711.   if (disp.cury) {
  712.     dsscroll(0, disp.winheight, disp.cury);
  713.     disp.cury = 0;
  714.   }
  715.   dsfunction(ERASETO_EOS);
  716.   dscursoron();
  717. }
  718.  
  719. #ifdef TEKTRONICS        /*added RKNOP 940328*/
  720. void menu_totek(UBYTE mnum,UBYTE item,UBYTE sub)
  721. {
  722.   vt100_tek();
  723. }
  724.  
  725. void menu_tovt100(UBYTE mnum,UBYTE item,UBYTE sub)
  726. {
  727.   tek_vt100();
  728. }
  729. #endif
  730.  
  731. void menu_reset(UBYTE mnum, UBYTE item, UBYTE sub)
  732. {
  733.   dscursoroff();
  734.   dsfunction(RESET_DISPLAY);
  735.   dscursoron();
  736. }
  737.  
  738. void menu_flush(UBYTE mnum, UBYTE item, UBYTE sub)
  739. {
  740.   nioctl(NIO_FLUSH, 0, 0);
  741. }
  742.  
  743. void menu_break(UBYTE mnum, UBYTE item, UBYTE sub)
  744. {
  745.   nioctl(NIO_BREAK, 0, 0);
  746. }
  747.  
  748. #ifdef OWNICONIFY
  749. void menu_iconify(UBYTE mnum, UBYTE item, UBYTE sub)
  750. {
  751.   unmapwindow();
  752.   iconify();
  753. }
  754. #endif
  755.  
  756. /*
  757.  * Note: listen must be just before unlisten in its menu!
  758.  */
  759. void menu_listen(UBYTE mnum, UBYTE item, UBYTE sub)
  760. {
  761.   menu_state(mnum, item, sub, FALSE);
  762.  
  763.   /* Enable UnListen if nabort() is successful */
  764.   if (!nabort())
  765.     menu_state(mnum, item + 1, sub, TRUE);
  766.   else
  767.     /* otherwise, re-enable us */ 
  768.     menu_state(mnum, item, sub, TRUE);
  769.  
  770.   ResetMenuStrip(w, &cmdmenu);
  771. }
  772.  
  773. void menu_unlisten(UBYTE mnum, UBYTE item, UBYTE sub)
  774. {
  775.   menu_state(mnum, item, sub, FALSE);
  776.  
  777.   /* Enable Listen if nabort() is successful */
  778.   if (nabort())
  779.     menu_state(mnum, item - 1, sub, TRUE);
  780.   else
  781.     /* otherwise, re-enable us */ 
  782.     menu_state(mnum, item, sub, TRUE);
  783.  
  784.   ResetMenuStrip(w, &cmdmenu);
  785. }
  786.  
  787. void menu_quit(UBYTE mnum, UBYTE item, UBYTE sub)
  788. {
  789.   dsquit();
  790.   amigaquit();
  791.   exit(0);
  792. }
  793.  
  794. /*
  795.  * Callback routines for setup menu -- prototypes on <napsaprefs.h>
  796.  */
  797. void change_cursor(int mode)
  798. {
  799.   dscursoroff();
  800.   disp.visual = mode;
  801.   dscursoron();
  802. }
  803.  
  804. /* added RKNOP 940328 */
  805. void change_ansi_LNM(int on)
  806. {  np.ansi_LNM=on;
  807. }
  808. /* end added RKNOP 940328 */
  809.  
  810. void change_invert(int on)
  811. {
  812.   dsinvert(on ? INVERT_ON : INVERT_OFF);
  813. }
  814.  
  815. void change_mode80(int on)
  816. {
  817.   if (on)
  818.     dssizewindow(80, 0, 1);
  819.   else
  820.     WindowLimits(w, 0, 0, -1, -1);
  821. #if 0
  822.   redraw_display(1);
  823. #endif
  824. }
  825.  
  826. void change_national(int national)
  827. {
  828.   (void) redraw_display(0);
  829. }
  830.  
  831. void change_nation(int nation)
  832. {
  833.   setnation(nation);
  834.   if (np.national == NAT_7BIT)
  835.     (void) redraw_display(0);
  836. }
  837.  
  838. /*
  839.  * The text of the menu, callback function and the HotKey for it. 
  840.  */
  841. struct menudef {
  842.   char  *text;
  843.   void (*call_f)(UBYTE mnum, UBYTE item, UBYTE sub);
  844.   char com;
  845.   unsigned ser : 1;        /* active only with serial */
  846.   unsigned off : 1;        /* not active by default */
  847. };
  848.  
  849. static struct menudef cmd_items[] = 
  850. {
  851.   { "Clear Screen", menu_clear, 'S', }, 
  852. #ifdef TEKTRONICS          /*added RKNOP 940328*/
  853.   { "To Tek4010", menu_totek, 'G', },
  854.   { "To VT102", menu_tovt100, 'T', },
  855. #endif
  856.   { "Soft Reset", menu_reset, 'R', }, 
  857.   { "Flush", menu_flush, 'F', },
  858.   { "Break", menu_break, 'B', 1, },
  859.   { "Listen", menu_listen, 'L', 1, 1, },
  860.   { "Unlisten", menu_unlisten, 'U', 1, },
  861.   { "Quit", menu_quit, 'Q', },
  862.   { NULL, },
  863. };
  864.  
  865. static struct menudef edit_items[] = 
  866. {
  867.   { "Copy", menu_copy, 'C', },
  868.   { "Paste", menu_paste, 'V', },
  869.   { "Move", menu_move, 'M', }, 
  870.   { "Execute", menu_execute, 'E', }, 
  871.   { NULL, },
  872. };
  873.  
  874. /*
  875.  * Initialize a menu item
  876.  */
  877. static struct MenuItem *inititem(struct MenuItem **first, 
  878.                  struct MenuItem *last, 
  879.                  const char *str, char com)
  880. {
  881.   struct IntuiText *it;
  882.   struct MenuItem *mi;
  883.  
  884.   /*
  885.    * Templates
  886.    */
  887.   static struct MenuItem protoitem = {
  888.     NULL, 0, 0, 0, 0, HIGHCOMP | ITEMTEXT | ITEMENABLED,
  889.     0, NULL, NULL, 0, NULL, 0
  890.     };
  891.  
  892.   static struct IntuiText prototext = {
  893.     0, 1, JAM2, 0, 0, NULL, NULL, NULL
  894.     };
  895.  
  896.   mi = (struct MenuItem *)
  897.     AllocVec(sizeof(*mi) + sizeof(*it), MEMF_PUBLIC);
  898.   if (last)
  899.     last->NextItem = mi;
  900.   else
  901.     *first = mi;
  902.  
  903.   if (mi == NULL) {
  904.     fatalError(MEMORY_ERROR_MSG);
  905.   }
  906.  
  907.   it = (struct IntuiText *)(mi + 1);
  908.   *mi = protoitem; *it = prototext;
  909.   mi->TopEdge = last ? last->TopEdge + w->WScreen->RastPort.TxHeight + 1 : 0;
  910.   mi->Height = w->WScreen->RastPort.TxHeight + 1;
  911.   mi->Width = ITEMWIDTH(str);
  912.   mi->ItemFill = (APTR)it;
  913.   if (com) {
  914.     mi->Command = com;
  915.     mi->Flags |= COMMSEQ;
  916.     mi->Width += CMDWIDTH(mi->Command);
  917.   }
  918.   it->TopEdge = 1;
  919.   it->IText = (UBYTE *)str;
  920.   return mi;
  921. }
  922.  
  923. static void initmenu(struct Menu *menu, struct menudef newmenu[])
  924. {
  925.   struct MenuItem *li = NULL;
  926.   long width = 0;
  927.  
  928.   menu->Width = MENUWIDTH(*menu);
  929.  
  930.   for (; newmenu->text; newmenu++) {
  931.     li = inititem(&menu->FirstItem, li, newmenu->text, newmenu->com);
  932.     width = (li->Width > width) ? li->Width : width;
  933.  
  934.     if (iotype != serial && newmenu->ser || newmenu->off) {
  935.       li->Flags &= ~ITEMENABLED;
  936.     }
  937.   }
  938.   for (li = menu->FirstItem; li; li = li->NextItem)
  939.     li->Width = width;
  940. }
  941.  
  942. /*
  943.  * Initialize and show menus
  944.  */
  945. void initmenus(void)
  946. {
  947.   if (!cmdmenu.FirstItem) {
  948.     long width, me;
  949.     const char *mtxt;
  950.     struct MenuItem *li;
  951.  
  952.     initmenu(&cmdmenu, cmd_items);
  953.     initmenu(&editmenu, edit_items);
  954.     editmenu.LeftEdge = cmdmenu.LeftEdge + cmdmenu.Width;
  955.     setupmenu.Width = MENUWIDTH(setupmenu);
  956.     setupmenu.LeftEdge = editmenu.LeftEdge + editmenu.Width;
  957.  
  958.     for (me = 0, li = NULL, width = 0; mtxt = setup_items[me].title; me++) {
  959.       li = inititem(&setupmenu.FirstItem, li, mtxt, 0);
  960.       if (mtxt = setup_items[me].texts) {
  961.     int subi, val = getsetup(me);
  962.     struct MenuItem *si = NULL;
  963.     
  964.     for (subi = 0; *mtxt; subi++) {
  965.       si = inititem(&li->SubItem, si, mtxt, 0);
  966.       si->MutualExclude = ~(1<<subi);
  967.       si->Flags |= CHECKIT;
  968.       if (subi == val)
  969.         si->Flags |= CHECKED;
  970.       while (*mtxt++)
  971.         ;
  972.       si->Width += CHECKWIDTH;
  973.       ((struct IntuiText *)si->ItemFill)->LeftEdge = CHECKWIDTH;
  974.     }
  975.       } else {
  976.     li->Flags |= CHECKIT | MENUTOGGLE;
  977.     if (getsetup(me))
  978.       li->Flags |= CHECKED;
  979.     li->Width += CHECKWIDTH;
  980.     ((struct IntuiText *)li->ItemFill)->LeftEdge = CHECKWIDTH;
  981.       }
  982.       width = (li->Width > width) ? li->Width : width;
  983.     }
  984.     for (li = setupmenu.FirstItem; li; li = li->NextItem) {
  985.       struct MenuItem *si;
  986.       int subwidth = width / 2;
  987.  
  988.       for (si = li->SubItem; si; si = si->NextItem) {
  989.     si->TopEdge += w->WScreen->RastPort.TxHeight + 2;
  990.     si->LeftEdge = setupmenu.Width;
  991.     subwidth = (si->Width > subwidth) ? si->Width : subwidth;
  992.       }
  993.       for (si = li->SubItem; si; si = si->NextItem) {
  994.     si->Width = subwidth;
  995.       }
  996.       li->Width = width;
  997.     }
  998.  
  999. #if 0
  1000.     nationalmenu.Width = MENUWIDTH(nationalmenu);
  1001.  
  1002.     for (me = 0, li = NULL, width = 0; mtxt = getnationname(me); me++) {
  1003.       li = inititem(&nationalmenu.FirstItem, li, mtxt, 0);
  1004.       li->MutualExclude = ~(1<<me);
  1005.       li->Flags |= CHECKIT;
  1006.       if (me == getnationnumber())
  1007.     li->Flags |= CHECKED;
  1008.       width = (li->Width > width) ? li->Width : width;
  1009.     }
  1010.     width += CHECKWIDTH;
  1011.     for (li = nationalmenu.FirstItem; li; li=li->NextItem) {
  1012.       li->Width = width;
  1013.       ((struct IntuiText *)li->ItemFill)->LeftEdge = CHECKWIDTH;
  1014.     }
  1015. #endif
  1016.   }
  1017.  
  1018.   SetMenuStrip(w, &cmdmenu);
  1019. }
  1020.  
  1021. void deinitmenus(void)
  1022. {
  1023.   struct Menu *menu;
  1024.   struct MenuItem *mi, *ni, *si, *sni;
  1025.  
  1026.   for (menu = &cmdmenu; menu; menu = menu->NextMenu) {
  1027.     for (mi = menu->FirstItem; mi; mi = ni) {
  1028.       ni = mi->NextItem;
  1029.       for (si = mi->SubItem; si; si = sni) {
  1030.     sni = si->NextItem;
  1031.     FreeVec(si), si = NULL;
  1032.       }
  1033.       FreeVec(mi), mi = NULL;
  1034.     }
  1035.     menu->FirstItem = NULL;
  1036.   }
  1037. }
  1038.  
  1039. /*
  1040.  * Setup menu dispatcher
  1041.  */
  1042. static void domenu_setup(register UBYTE which, register BYTE sub)
  1043. {
  1044.   register BYTE new, cleared = 0;
  1045.   struct MenuItem *mi, *si;
  1046.   
  1047.   /* We will get no extra events for extended selection */
  1048.   for (which = 0, mi = setupmenu.FirstItem; mi; mi = mi->NextItem, which++) {
  1049.     if (si = mi->SubItem) {
  1050.       for (sub = 0; si; sub++, si = si->NextItem) {
  1051.     if ((si->Flags & CHECKED) == CHECKED)
  1052.       break;
  1053.       }
  1054.       /* None was checked.. */
  1055.       if (!si)
  1056.     sub = -1;
  1057.     } else {
  1058.       sub = (mi->Flags & CHECKED) == CHECKED;
  1059.     }
  1060.     new = changesetup(which, sub);
  1061.     if (sub != new) {
  1062.       if (!cleared)
  1063.     ClearMenuStrip(w);
  1064.       cleared = 1;
  1065.       if (si = mi->SubItem) {
  1066.     /* Check an item in submenu */
  1067.     for (sub = 0; si; sub++, si = si->NextItem) {
  1068.       if (sub == new)
  1069.         si->Flags |= CHECKED;
  1070.       else
  1071.         si->Flags &= ~CHECKED;
  1072.     }
  1073.       } else {
  1074.     if (new)
  1075.         mi->Flags |= CHECKED;
  1076.       else
  1077.         mi->Flags &= ~CHECKED;
  1078.       }
  1079.     }
  1080.   }
  1081.  
  1082.   /*
  1083.    * Redraw menu
  1084.    */
  1085.   if (cleared)
  1086.     ResetMenuStrip(w, &cmdmenu);
  1087. }
  1088.  
  1089. /*
  1090.  * National menu dispatcher
  1091.  */
  1092. static void domenu_nation(register UBYTE nation, register UBYTE sub)
  1093. {
  1094.   setnation(nation);
  1095.   (void) redraw_display(0);
  1096. }
  1097.  
  1098. /*
  1099.  * Menu dispatcher
  1100.  */
  1101. void domenu(register struct IntuiMessage *msg)
  1102. {
  1103.   register ULONG code = msg->Code;
  1104.   register UBYTE mnum = MENUNUM(code);
  1105.   register UBYTE item = ITEMNUM(code);
  1106.   register UBYTE sub  = SUBNUM(code);
  1107.  
  1108.   ReplyMsg(msg), msg = NULL;
  1109.  
  1110.   /* so we know that item is always valid */
  1111.   if (code == MENUNULL || mnum == NOMENU || item == NOITEM)
  1112.     return;
  1113.  
  1114.   switch (mnum) {
  1115.   case MENU_CMD:
  1116.     if (cmd_items[item].call_f)
  1117.       cmd_items[item].call_f(mnum, item, sub);
  1118.     break;
  1119.   case MENU_EDIT:
  1120.     if (edit_items[item].call_f)
  1121.       edit_items[item].call_f(mnum, item, sub);
  1122.     break;
  1123.   case MENU_SETUP:
  1124.     domenu_setup(item, sub);
  1125.     break;
  1126. #if 0
  1127.   case MENU_NATIONAL:
  1128.     domenu_nation(item, sub);
  1129.     break;
  1130. #endif
  1131.   }
  1132. }
  1133.